package com.caifu.util;

import com.alibaba.fastjson.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Auther: Lyf
 * @Date: 2020/7/8 09:36
 * @Description:
 */
@PropertySource(value = {"classpath:definition.properties"},encoding = "utf-8")
public class Util {

    @Value("${file.upload.path}")
    private static String fileUploadPath;
    @Value("${file.upload.result.path}")
    private static String fileUploadResultPath;
    //分页数量
    public final static int PAGE_SIZE_FIVE=5;
    public final static int PAGE_SIZE_SIX=6;
    public final static int PAGE_SIZE_TEN=10;

    /**
     * 功能描述: 日期转字符串
     *
     * @auther: Lyf
     * @date: 2020/7/8 9:47
     * @param:
     * @return:
     */
    public static String dateToString(Date date,String format){
        try {
            if(date == null){
                date = new Date();
            }
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.format(date);
        }catch (Exception e){
            return  "";
        }
    }

    /**
     * 功能描述: 字符串转日期
     *
     * @auther: Lyf
     * @date: 2020/7/8 9:51
     * @param:
     * @return:
     */
    public static Date stringToDate(String date,String format){
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.parse(date);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 功能描述: 日期格式字符串转日期格式字符串
     *
     * @auther: Lyf
     * @date: 2020/7/8 9:51
     * @param:
     * @return:
     */
    public static String stringDateToStringDate(String date,String oldFormat,String newFormat){
        try {
            SimpleDateFormat oldSdf = new SimpleDateFormat(oldFormat);
            SimpleDateFormat newSdf = new SimpleDateFormat(newFormat);
            return newSdf.format(oldSdf.parse(date));
        }catch (Exception e){
            return null;
        }
    }

    /**
     * 功能描述: 日期推算
     *
     * @auther: Lyf
     * @date: 2020/7/8 10:23
     * @param: date 需要前推的日期（传递null默认当前日期）
     * @param: days 需要前推的天数
     * @return:
     */
    public static String dateCalculation(Date date,int days){
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        if(date == null) {
            date = new Date();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, days);
        date = (Date) calendar.getTime();
        String day = df.format(date);
        return day;
    }

    /**
     * 功能描述: 获取某年某月的所有日期
     *
     * @auther: Lyf
     * @date: 2020/11/6 9:15
     * @param:
     * @return:
     */
    public static List<String> getMonthFullDay(int year , int month, String format){
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        List<String> fullDayList = new ArrayList<>();
        // 获得当前日期对象
        Calendar cal = Calendar.getInstance();
        cal.clear();// 清除信息
        cal.set(Calendar.YEAR, year);
        // 1月从0开始
        cal.set(Calendar.MONTH, month-1 );
        // 当月1号
        cal.set(Calendar.DAY_OF_MONTH,1);
        int count = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        for (int j = 1; j <= count ; j++) {
            fullDayList.add(dateFormat.format(cal.getTime()));
            cal.add(Calendar.DAY_OF_MONTH,1);
        }
        return fullDayList;
    }

    public static int getDateWeek(int addMonth){
        int week;
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MONTH,addMonth);
        cal.set(Calendar.DAY_OF_MONTH,1);
        System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime()));
        int weekDay = cal.get(Calendar.DAY_OF_WEEK);
        if(Calendar.MONDAY == weekDay){
            week = 0;
        }else if(Calendar.TUESDAY==weekDay){
            week = 1;
        }else if(Calendar.WEDNESDAY==weekDay){
            week = 2;
        }else if(Calendar.THURSDAY==weekDay){
            week = 3;
        }else if(Calendar.FRIDAY==weekDay){
            week = 4;
        }else if(Calendar.SATURDAY==weekDay){
            week = 5;
        }else {
            week = 6;
        }
        return week;
    }

    /**
     * 功能描述: 日期推算
     *
     * @auther: Lyf
     * @date: 2020/7/8 10:23
     * @param: date 需要前推的日期（传递null默认当前日期）
     * @param: days 需要前推的年
     * @return:
     */
    public static String dateCalculation_year(Date date,int years){
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        if(date == null) {
            date = new Date();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, years);
        date = (Date) calendar.getTime();
        String day = df.format(date);
        return day;
    }

    /**
     * 功能描述: 日期推算
     *
     * @auther: Lyf
     * @date: 2020/7/8 10:23
     * @param: date 需要前推的日期（传递null默认当前日期）
     * @param: days 需要前推的月
     * @return:
     */
    public static String dateCalculation_month(Date date,int month,String format){
        DateFormat df = new SimpleDateFormat(format);
        if(date == null) {
            date = new Date();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, month);
        date = (Date) calendar.getTime();
        String day = df.format(date);
        return day;
    }

    /**
     * 功能描述: 日期推算
     *
     * @auther: Lyf
     * @date: 2020/7/8 10:23
     * @param: date 需要前推的日期字符串
     * @param: format 需要前推的日期字符串格式
     * @param: days 需要前推的天数
     * @return:
     */
    public static String dateCalculation(String date,String format,int days){
       //DateFormat df = new SimpleDateFormat("YYYY-MM-DD");
        DateFormat dsf = new SimpleDateFormat(format);
        if(StringUtils.isNotBlank(date)) {
            try {
                Date d = dsf.parse(date);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(d);
                calendar.add(Calendar.DAY_OF_MONTH, days);
                d = (Date) calendar.getTime();
                String day = dsf.format(d);
                return day;
            }catch (Exception e){
                return "";
            }
        }else{
            return "";
        }
    }

    /**
     * 功能描述: 生成随机数字和字母
     *
     * @auther: Lyf
     * @date: 2020/7/8 10:38
     * @param: length  生成位数
     * @return:
     */
    public static String getStringRandom(int length) {
        String val = "";
        Random random = new Random();
        //参数length，表示生成几位随机数
        for(int i = 0; i < length; i++) {
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
            //输出字母还是数字
            if( "char".equalsIgnoreCase(charOrNum) ) {
                //输出是大写字母还是小写字母
                int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
                val += (char)(random.nextInt(26) + temp);
            } else if( "num".equalsIgnoreCase(charOrNum) ) {
                val += String.valueOf(random.nextInt(10));
            }
        }
        return val;
    }

    /**
     * 功能描述: 根据uuid生成不重复的文件名
     *
     * @auther: Lyf
     * @date: 2020/7/20 10:26
     * @param:
     * @return:
     */
    public static String getNewFileName(String fileName){
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        return UUID.randomUUID().toString().replace("-","") + suffix;
    }

    public static JSONObject uploadFile(MultipartFile file, String path){
        JSONObject obj = new JSONObject();
        try{
            String fileName = file.getOriginalFilename();
            String newFileName = getNewFileName(fileName);

            String now = dateToString(null,"yyyyMMdd");

            String newPath = fileUploadPath + now + "/" + path + "/" + newFileName;
            String resultPath = fileUploadResultPath + now + "/" + path + "/" + newFileName;

            File newFile = new File(newPath);
            file.transferTo(newFile);

            obj.put("path",resultPath);
            obj.put("name",fileName);
            obj.put("code","success");
        }catch (Exception e){
            obj.put("code","error");
            e.printStackTrace();
        }
        return obj;
    }
    
    /**
     * 获取指定长度的随机字符串
     * 2020年8月14日 
     * codeBy szt
     */
    public static String getRandom(int n) {
    	StringBuffer buf = new StringBuffer();
    	for(int i=0;i<n;i++) {
    		buf.append(new Random().nextInt(9));
    	}
    	return buf.toString();
    	    
    }
    
    /**
     * 空字符串转成“”
     * 2020年8月14日 
     * codeBy szt
     */
    public static String Null2EmptyTrim(String str) {
		if (str == null||"".equals(str)) {
			return "";
		} 
		return str.trim();
	}

    /**
     * 获取当前年份
     * 2020年8月14日
     * codeBy szt
     */
    public static String currentYear(){
        Date date=new Date();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy");
        return dateFormat.format(date);
    }

    /**
     * 获取当前年份月份
     * 2020年8月14日
     * codeBy szt
     */
    public static String currentYearMonth(){
        Date date=new Date();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyMM");
        return dateFormat.format(date);
    }
    
    /**
     * 获取当前日期
     * 2020年8月14日 
     * codeBy szt
     */
  	public static String currentDate(){
  		Date date=new Date();
  		SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyMMdd");
  		return dateFormat.format(date);
  	}

    /**
     * 获取当前时间
     * 2020年8月14日
     * codeBy szt
     */
    public static String currentDateTime(){
        Date date=new Date();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyMMddHHmmss");
        return dateFormat.format(date);
    }

    /**
     * 功能描述: 14位时间转时间戳
     * @Param:  [val]
     * @Author: szt
     * @Date:   2020/10/13
     */
    public static long timeToStamp(String val) throws ParseException {
        DateFormat dsf = new SimpleDateFormat("yyyymmddhhmmss");
        Date d = dsf.parse(val);
        return d.getTime();
    }

    /**
     * 功能描述: 将对象转为json打印
     * @Param:  [object]
     * @Author: szt
     * @Date:   2020/11/6
     */
    public static void pringJson(Object object, String str){
        if("obj".equals(str)){
            JSONObject json = JSONObject.fromObject(object);
            System.out.println(json.toString(2));
        }else if("arr".equals(str)){
            JSONArray json = JSONArray.fromObject(object);
            System.out.println(json.toString(2));
        }
    }

    /**
     * 功能描述: 非空字符串转为""
     * @Param:  [str]
     * @Author: szt
     * @Date:   2020/9/9
     */
    public static String null2EmptyTrim(String str) {
        if (str == null||"".equals(str.trim())) {
            return "";
        }
        return str.trim();
    }

    /**
     * 功能描述: 非空字符串转为""
     * @Param:  [str]
     * @Author: szt
     * @Date:   2020/9/9
     */
    public static double null2EmptyTrimDouble(Double str) {
        if (str == null) {
            return 0;
        }
        return str;
    }

    /**
     * 功能描述: 获取19位订单号（13时间戳+6位随机数）
     * @Author: szt
     * @Date:   2020/10/15
     */
    public static  String getOrderNumber(){
        int r1=new Random().nextInt(99999) + 1;;//产生6个0-9的随机数
        int r2=(int)(Math.random()*(10))+1;
        long now = System.currentTimeMillis();//一个13位的时间戳
        String paymentID =String.valueOf(r1)+String.valueOf(r2)+String.valueOf(now);// 订单ID
        return paymentID;
    }

    /**
     * 判断传入的字符串是否为空 || 为空串
     * @param str ： 需要判断的字符串
     * @return ： 判断的结果
     * <li> true ：为空
     * <li> false ：不为空
     */
    public static boolean isNull(String str) {
        return str == null || "".equals(str.trim())? true : false;
    }

    /**
     * 判断传入的字符串是否不为空 && 不为空串
     * @param str ： 需要判断的字符串
     * @return ： 判断的结果
     * <li> true ：不为空
     * <li> false ：为空
     */
    public static boolean isNotNull(String str) {
        return !isNull(str);
    }

    /**
     * 重载方法,判断多个字符串或可转换字符窜的对象是否为空
     * @param flag : 判断条件
     * <li> true : 逻辑且
     * <li> false : 逻辑或
     * @param objArr : 需要判断的所有字符串或可以tostring的对象
     * @return : 判断的结果
     * <li> true : 不为空
     * <li> false : 为空
     */
    public static boolean isNotNull(boolean flag, Object... objArr) {
        boolean resultFlag = false;

        // 判断传入的数组是否为空
        if (objArr != null && objArr.length > 0) {
            // 不为空 --> 迭代数组
            for (Object obj : objArr) {
                // 判断是逻辑且 | 逻辑或
                if (flag) {
                    // 逻辑且 --> 都不为空 --> 有一个为空就为false
                    if (obj == null || isNull(obj.toString())) {
                        // 有为空 --> 直接结束返回false
                        return false;
                    }
                    // 不为空，继续循环
                } else {
                    // 逻辑或 --> 有一个不为空就行
                    if (obj != null && isNotNull(obj.toString())) {
                        // 有不为空的 --> 直接返回true
                        return true;
                    }
                    // 为空，继续循环
                }
            }
            // 迭代结束 --> 判断是逻辑且 | 逻辑或
            if (flag) {
                // 逻辑且 --> 全不为空 --> 返回true
                resultFlag = true;

            }
            // 逻辑或 --> 全为空 --> 返回默认的false
        }
        // 为空 --> 返回默认的false

        return resultFlag;
    }

    /**
     * 重载方法,判断多个字符串或可转换字符窜的对象是否不为空
     * @param flag : 判断条件
     * <li> true : 逻辑且
     * <li> false : 逻辑或
     * @param objArr : 需要判断的所有字符串或可以tostring的对象
     * @return : 判断的结果
     * <li> true : 为空
     * <li> false : 不为空
     */
    public static boolean isNull(boolean flag, Object... objArr) {
        boolean resultFlag = false;

        // 判断是逻辑且 | 逻辑或
        if (flag) {
            // 逻辑且 --> isNotNull的逻辑或,取反
            resultFlag = !isNotNull(false, objArr);

        } else {
            // 逻辑或 --> isNotNull的逻辑且,取反
            resultFlag = !isNotNull(true, objArr);
        }

        return resultFlag;
    }

    /**
     * 判断传入的对象是否为空
     * @param obj : 需要判断的对象
     * @return : 判断的结果
     * <li>true : 为空</li>
     * <li>false : 不为空</li>
     */
    public static boolean isNull(Object obj)
    {
        return obj == null || "".equals(obj.toString().trim());
    }


    /**
     * 判断传入的对象是否不为空
     * @param obj : 需要判断的对象
     * @return : 判断的结果
     * <li>true : 不为空</li>
     * <li>false : 为空</li>
     */
    public static boolean isNotNull(Object obj)
    {
        return !isNull(obj);
    }



    /**
     * Map转实体类
     * @param map 需要初始化的数据
     * @param entity  需要转化成的实体类
     * @return T
     */
    public static <T> T mapToEntity(Map<String, Object> map, Class<T> entity) {
        T t = null;
        try {
            t = entity.newInstance();
            for(Field field : entity.getDeclaredFields()) {
                if (map.containsKey(field.getName())) {
                    boolean flag = field.isAccessible();
                    field.setAccessible(true);
                    Object object = map.get(field.getName());
                    if (object!= null && field.getType().isAssignableFrom(object.getClass())) {
                        field.set(t, object);
                    }
                    field.setAccessible(flag);
                }
            }
            return t;
        } catch (InstantiationException | IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 生成Token
     * Token：Nv6RRuGEVvmGjB+jimI/gw==
     *
     */
    public static String makeToken() {
        String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";
        //数据指纹   128位长   16个字节  md5
        try {
            MessageDigest md = MessageDigest.getInstance("md5");
            byte md5[] = md.digest(token.getBytes());
            //base64编码--任意二进制编码明文字符   adfsdfsdfsf
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(md5);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }



    public static Object checkNull(Object obj) {
        Class<? extends Object> clazz = obj.getClass();
        // 获取实体类的所有属性，返回Field数组
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            // 可访问私有变量
            field.setAccessible(true);
            // 获取属性类型
            String type = field.getGenericType().toString();
            // 如果type是类类型，则前面包含"class "，后面跟类名
            if ("class java.lang.String".equals(type)) {
                // 将属性的首字母大写
                String methodName = field.getName().replaceFirst(field.getName().substring(0, 1),
                        field.getName().substring(0, 1).toUpperCase());
                try {
                    Method methodGet = clazz.getMethod("get" + methodName);
                    // 调用getter方法获取属性值
                    String str = (String) methodGet.invoke(obj);
                    if (StringUtils.isBlank(str)) {
                        // Method methodSet = clazz.getMethod("set" +
                        // methodName, new Class[] { String.class });
                        // methodSet.invoke(o, new Object[] { "" });
                        // 如果为null的String类型的属性则重新复制为空字符串
                        field.set(obj, field.getType().getConstructor(field.getType()).newInstance(""));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return obj;
    }
    public static int getAgeFromBirthTime(String birthTimeString) {
        // 先截取到字符串中的年、月、日
        String strs[] = birthTimeString.trim().split("-");
        int selectYear = Integer.parseInt(strs[0]);
        int selectMonth = Integer.parseInt(strs[1]);
        int selectDay = Integer.parseInt(strs[2]);
        // 得到当前时间的年、月、日
        Calendar cal = Calendar.getInstance();
        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH) + 1;
        int dayNow = cal.get(Calendar.DATE);

        // 用当前年月日减去生日年月日
        int yearMinus = yearNow - selectYear;
        int monthMinus = monthNow - selectMonth;
        int dayMinus = dayNow - selectDay;

        int age = yearMinus;// 先大致赋值
        if (yearMinus < 0) {// 选了未来的年份
            age = 0;
        } else if (yearMinus == 0) {// 同年的，要么为1，要么为0
            age = 0;
        } else if (yearMinus > 0) {
            if (monthMinus < 0) {// 当前月>生日月
                age --;
            } else if (monthMinus == 0) {// 同月份的，再根据日期计算年龄
                if (dayMinus < 0) {
                    age --;
                }
            } else if (monthMinus > 0) {
                age = age + 1;
            }
        }
        return age;
    }

    public static String getUuid(){
        return UUID.randomUUID().toString().replace("-","");
    }

    /**
     * 从对象A copy到 对象B
     * @param ob A
     * @param clazz B.class
     * @return B
     */
    public static <T> T copy(Object ob,Class<T> clazz){
        String oldOb = JSON.toJSONString(ob);
        return JSON.parseObject(oldOb, clazz);
    }

    /**
     * 功能描述: 获取日期当月天数
     * @Param:  [day  yyyyMMdd]
     * @Author: szt
     * @Date:   2020/11/26
     */
    public static int getDaysOfMonth(String day) throws Exception {
        DateFormat dsf = new SimpleDateFormat("yyyyMMdd");
        Calendar calendar = Calendar.getInstance();
        if(StringUtils.isNotBlank(day)) {
            Date d = dsf.parse(day);
            calendar.setTime(d);
        }
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 功能描述: 获取日期所在年份1月到当月数组
     * @Param:  [day]
     * @Author: szt
     * @Date:   2020/11/26
     */
    public static int[] getMonthArrOfYear(String day) throws Exception {
        DateFormat dsf = new SimpleDateFormat("yyyyMMdd");
        Calendar calendar = Calendar.getInstance();
        if(StringUtils.isNotBlank(day)) {
            Date d = dsf.parse(day);
            calendar.setTime(d);
        }
        int curMonth = calendar.getActualMaximum(Calendar.MONTH);
        int[] arr= new int[curMonth+1];
        for (int i = 0; i <=curMonth ; i++) {
            arr[i]=i+1;
        }
        return arr;
    }

    /**
     * 判断长度进行格式化日期
     * @param date
     * @return
     */
    public static String simpleDate(String date){
        String newDate = "";
        if(date == null || date.trim().equals("")){
            return newDate;
        }

        if(date.length() == 8){
            SimpleDateFormat sdf1=new SimpleDateFormat("yyyyMMdd");
            SimpleDateFormat sdf2=new SimpleDateFormat("yyyy-MM-dd");
            try {
                return sdf2.format(sdf1.parse(date));
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }

        if(date.length() == 14){

            SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
            SimpleDateFormat time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date tmpDate = new Date();
            try {
                tmpDate = df.parse(date);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return time.format(tmpDate);
        }
        return newDate;
    }

    //金额验证
    public static boolean isSalaryNumber(String str){
        Pattern pattern=Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,2})?$"); // 判断小数点后2位的数字的正则表达式
        Matcher match=pattern.matcher(str);
        if(match.matches()==false){
            return false;
        }else{
            return true;
        }
    }
}
